import { Inject, Logger, Provide } from '@midwayjs/decorator';
import { InjectEntityModel } from '@midwayjs/orm';
import { Brackets, getConnection, Repository, In } from 'typeorm';
import { WeiboBlogEntity } from '../entity/blog';
import { BaseService, ICoolCache, CoolCommException } from '@cool-midway/core';
import { CreateWeiBoDTO } from '../dto/weibo';
import { WeiboBlogPhotoEntity } from '../entity/blogPhoto';
import { WeiboBlogGoodsEntity } from '../entity/blogGoods';
import { WeiboTagsEntity } from '../entity/tags';
import { ILogger } from '@midwayjs/logger';
import { WeiboBlogTagEntity } from '../entity/blogTag';
import { WeiboBlogLoveEntity } from '../entity/blogLove';
import { WeiboBlogCollectEntity } from '../entity/blogCollect';
import { WeiboBlogActivityEntity } from '../entity/blogActivity';
import { UserInfoEntity } from '../../user/entity/info';
import * as _ from 'lodash';
import { Utils } from '../../../comm/utils';
import { UserFollowEntity } from '../../user/entity/userFollow';

/**
 * 商品
 */
@Provide()
export class WeiboBlogService extends BaseService {
  @InjectEntityModel(WeiboBlogEntity)
  weiboBlogEntity: Repository<WeiboBlogEntity>;

  @InjectEntityModel(WeiboTagsEntity)
  weiboTagsEntity: Repository<WeiboTagsEntity>;

  @InjectEntityModel(WeiboBlogLoveEntity)
  weiboBlogLoveEntity: Repository<WeiboBlogLoveEntity>;

  @InjectEntityModel(WeiboBlogPhotoEntity)
  weiboBlogPhotoEntity: Repository<WeiboBlogPhotoEntity>;

  @InjectEntityModel(WeiboBlogCollectEntity)
  weiboBlogCollectEntity: Repository<WeiboBlogCollectEntity>;

  @InjectEntityModel(WeiboBlogTagEntity)
  weiboBlogTagEntity: Repository<WeiboBlogTagEntity>;

  @InjectEntityModel(UserInfoEntity)
  userInfoEntity: Repository<UserInfoEntity>;

  @InjectEntityModel(WeiboBlogActivityEntity)
  weiboBlogActivityEntity: Repository<WeiboBlogActivityEntity>;

  @InjectEntityModel(UserFollowEntity)
  userFollowEntity: Repository<UserFollowEntity>;

  @Inject('cool:cache')
  coolCache: ICoolCache;

  @Logger()
  logger: ILogger;

  @Inject()
  utils: Utils;

  async top(offset: number, limit: number) {
    return this.weiboBlogEntity
      .createQueryBuilder()
      .where(
        'WeiboBlogEntity.isAudit = 1 AND WeiboBlogEntity.count_love > 10 AND TO_DAYS(WeiboBlogEntity.createTime) = TO_DAYS(NOW())'
      )
      .offset(offset)
      .limit(limit)
      .orderBy('WeiboBlogEntity.count_love', 'DESC')
      .getMany();
  }

  async create(query: CreateWeiBoDTO) {
    let resBlog = null;

    const conn = getConnection();
    const queryRunner = conn.createQueryRunner();
    await queryRunner.connect();
    await queryRunner.startTransaction();
    try {
      const blog = new WeiboBlogEntity();
      blog.comment = query.comment;
      blog.title = query.title;
      blog.pics = query.pics;
      blog.type = query.type || null;
      blog.video = query.video || null;
      blog.createTime = new Date();
      blog.userId = query.userId;
      blog.ipAddr = query.ipAddr;
      blog.isAudit = 1; //默认通过审核，后面再人工审核
      if (Array.isArray(query.goods)) {
        blog.goods = query.goods.toString();
      }
      if (Array.isArray(query.activity)) {
        blog.activity = query.activity.toString();
      }

      resBlog = await queryRunner.manager.save(WeiboBlogEntity, blog);

      // 插入图片
      const picsArr = query.pics.split(',') || [];
      if (Array.isArray(picsArr) && picsArr.length) {
        await Promise.all(
          picsArr.map(async v => {
            await queryRunner.manager.save(WeiboBlogPhotoEntity, {
              blogId: resBlog.id,
              image: v.toString(),
            });
          })
        );
      }

      //找#号内的内容
      const weiboTagss = [];
      // const tags = query.comment.match(/\#(.+?)\#/g); //#开头  # 结尾
      const tags = query.comment.match(/\#(.+?)\ /g); //#开头  空格 结尾

      if (Array.isArray(tags) && tags.length > 0) {
        await Promise.all(
          tags.map(async v => {
            let tag = new WeiboTagsEntity();
            // tag.name = v.replace('#', '').replace('#', '');
            tag.name = v.replace('#', '').replace(' ', '');
            tag.num = 1;
            const resTag = await this.weiboTagsEntity
              .createQueryBuilder()
              .where({ name: tag.name })
              .getOne();
            if (resTag) {
              tag = resTag;
              tag.num = Math.trunc(tag.num) + 1;
            }
            const saveTag = await queryRunner.manager.save(
              WeiboTagsEntity,
              tag
            );

            weiboTagss.push(saveTag.id);
            //补充关联关系
            await queryRunner.manager.save(WeiboBlogTagEntity, {
              tagId: saveTag.id,
              blogId: resBlog.id,
            });
          })
        );
      }

      //引用tag
      if (Array.isArray(query.tags)) {
        await Promise.all(
          query.tags.map(async v => {
            weiboTagss.push(v);
            await queryRunner.manager.save(WeiboBlogTagEntity, {
              tagId: v,
              blogId: resBlog.id,
            });
          })
        );
      }

      // 插入商品
      if (Array.isArray(query.goods) && query.goods.length) {
        await Promise.all(
          query.goods.map(async v => {
            await queryRunner.manager.save(WeiboBlogGoodsEntity, {
              blogId: resBlog.id,
              goodsId: v,
            });
          })
        );
      }

      // 插入活动
      if (Array.isArray(query.activity) && query.activity.length) {
        await Promise.all(
          query.activity.map(async v => {
            await queryRunner.manager.save(WeiboBlogActivityEntity, {
              blogId: resBlog.id,
              activityId: v,
            });
          })
        );
      }

      // #补充缓存
      if (weiboTagss) {
        await queryRunner.manager.save(WeiboBlogEntity, {
          id: resBlog.id,
          tags: weiboTagss.toString(),
        });
      }
      await queryRunner.commitTransaction();
    } catch (error) {
      this.logger.error('CouponsListService.sendCouponsToUser', error);
      await queryRunner.rollbackTransaction();
    } finally {
      await queryRunner.release();
    }

    return resBlog;
  }

  /**
   * 关注
   * @param blogId
   * @param userId
   * @returns
   */
  async love(blogId: number, userId: number) {
    const blogLove = await this.weiboBlogLoveEntity.findOne({
      where: { blogId, userId },
    });
    const blog = await this.weiboBlogEntity.findOne(blogId);
    let countLove = 0;
    if (blog.countLove && blog.countLove !== null) {
      countLove = Math.trunc(blog.countLove);
    }

    if (blogLove) {
      countLove--;
      await this.weiboBlogLoveEntity
        .createQueryBuilder()
        .delete()
        .where({ blogId, userId })
        .execute();
      await this.weiboBlogEntity
        .createQueryBuilder()
        .update()
        .where({ id: blogId })
        .set({ countLove })
        .execute();
      return 'cancel';
    } else {
      countLove++;
      await this.weiboBlogEntity
        .createQueryBuilder()
        .update()
        .where({ id: blogId })
        .set({ countLove: Math.trunc(blog.countLove) + 1 })
        .execute();
      await this.weiboBlogLoveEntity.save({ blogId, userId });
      return 'up';
    }
  }

  /**
   * 收藏
   * @param blogId
   * @param userId
   * @returns
   */
  async Collect(blogId: number, userId: number) {
    const blogCollect = await this.weiboBlogCollectEntity.findOne({
      where: { blogId, userId },
    });
    const blog = await this.weiboBlogEntity.findOne(blogId);
    console.log(',,,,,,', blogCollect, blog);

    if (blogCollect) {
      await this.weiboBlogCollectEntity
        .createQueryBuilder()
        .delete()
        .where({ blogId, userId })
        .execute();
      await this.weiboBlogEntity
        .createQueryBuilder()
        .update()
        .where({ id: blogId })
        .set({ countCollect: Math.trunc(blog.countCollect) - 1 })
        .execute();
      return 'cancel';
    } else {
      await this.weiboBlogEntity
        .createQueryBuilder()
        .update()
        .where({ id: blogId })
        .set({ countCollect: Math.trunc(blog.countCollect) + 1 })
        .execute();
      await this.weiboBlogCollectEntity.save({ blogId, userId });
      return 'up';
    }
  }

  /**
   *
   * @param ids
   * @param infoIgnoreProperty
   * @returns
   */
  async info(ids: number, infoIgnoreProperty?: string[]): Promise<any> {
    let blog = await this.weiboBlogEntity
      .createQueryBuilder('a')
      .select()
      .leftJoinAndSelect('a.photos', 'photosList')
      .where('a.id in (:ids)', { ids })
      .getOne();
    if (!blog) return {};
    if (blog.photos && blog.photos.length) {
      await Promise.all(
        blog.photos.map(async res => {
          res.image = await this.utils.toMedia(res.image);
          return res;
        })
      );
    }
    blog = await this.utils.transformMedia(blog, ['photo', 'video']);
    return blog;
  }

  async hasConllect(blogId, userId) {
    const res = await this.weiboBlogCollectEntity
      .createQueryBuilder()
      .where({ blogId, userId })
      .getOne();
    return res ? true : false;
  }

  async hasLove(blogId, userId) {
    const res = await this.weiboBlogLoveEntity
      .createQueryBuilder()
      .where({ blogId, userId })
      .getOne();
    return res ? true : false;
  }

  /**
   *
   * @param query my=true 查自己的
   * @param option
   * @param connectionName
   * @returns
   */
  async page(query: any, option?: any): Promise<any> {
    let {
      blogIds = [],
      type,
      page = 1,
      size = 15,
      order = 'a.id',
      sort = 'DESC',
      groupBy = 'a.id',
      my,
      userId,
      keyWord,
      isAudit,
      activityId = [],
    } = query;

    let blogList: any[] = [];
    const entry = this.weiboBlogEntity
      .createQueryBuilder('a')
      .select(
        'a.*,b.blog_id as love,c.blog_id as collect,d.headimgurl,d.nickname'
      )
      .where(
        new Brackets(qb => {
          qb.where('1 = 1');

          if (Array.isArray(blogIds) && blogIds.length) {
            qb.andWhere('a.id in (:blogIds)', { blogIds });
          }

          if (activityId) {
            activityId = `%${activityId}%`;
            qb.andWhere('a.activity like :activityId', { activityId });
          }

          if (type) {
            qb.andWhere('a.type in (:type)', { type });
          }

          if (my) {
            qb.andWhere('a.user_id = :userId', { userId });
          }

          if (!my && isAudit !== void 0) {
            qb.andWhere('a.is_audit = :isAudit', { isAudit });
          }

          //模糊查询
          if (keyWord) {
            keyWord = `%${keyWord}%`;
            qb.andWhere('a.title like :keyWord', { keyWord });
          }
        })
      )
      .leftJoin(WeiboBlogLoveEntity, 'b', 'a.id = b.blog_id')
      .leftJoin(WeiboBlogCollectEntity, 'c', 'a.id = c.blog_id')
      .leftJoin(UserInfoEntity, 'd', 'a.user_id = d.id')
      .groupBy(groupBy)
      .offset(size * (page - 1))
      .limit(size);
    if (Array.isArray(blogIds) && blogIds.length) {
      blogList = await entry
        .orderBy('field(a.id,' + blogIds.toString() + ')')
        .getRawMany();
    } else {
      blogList = await entry
        .orderBy(order, sort == 'DESC' ? 'DESC' : 'ASC')
        .getRawMany();
    }

    blogList.map(res => {
      blogIds.push(res.id);
    });
    const set = new Set(blogIds);

    let photosList = [];
    if ([...set].length > 0) {
      photosList = await this.weiboBlogPhotoEntity
        .createQueryBuilder('a')
        .where('a.blog_id in (:blogIds)', { blogIds: [...set] })
        .getMany();
    }

    photosList = await this.utils.transformMedia(photosList, ['image']);
    blogList = await this.utils.transformMedia(blogList, ['photo']);

    if (photosList.length && photosList.length > 0) {
      blogList.map((blog, k) => {
        const photos = [];
        photosList.map(photo => {
          if (blog.id == photo.blogId) {
            photos.push(photo);
          }
        });
        blogList[k]['photos'] = photos;
      });
    }

    return {
      list: blogList,
      pagination: {
        page,
        size,
        total: -1,
      },
    };
  }

  /**
   * 设计新星
   * @param query 
   * @returns 
   */
  async findHotWeiboList(query: any) {
    let { order = "id", page = 1, size = 15 } = query
    return await this.weiboBlogEntity.createQueryBuilder()
      .select("*")
      .addSelect('SUM(count_love+count_collect)', 'ranking')
      .where(
        new Brackets(qb => {
          qb.where('1 = 1');
        })
      )
      .groupBy(order)
      .orderBy('createTime', 'DESC')
      .addOrderBy('ranking','DESC')
      .offset(size * (page - 1))
      .limit(size)
      .getRawMany();
  }

  /**
   * 推荐
   * @param ids
   */
  async recommends(ids: [], page: any): Promise<any> {
    const blogList = null;
    const tagsList = await this.weiboBlogTagEntity
      .createQueryBuilder('a')
      .where(
        new Brackets(qb => {
          if (ids && ids.length > 0) {
            qb.where('a.tag_id in (:ids) ', { ids });
          } else {
            qb.where('RAND()');
          }
        })
      )
      .getMany();

    const blogIds = tagsList.map(v => {
      return v.blogId;
    });
    console.log('blogIds====>', blogIds);

    const set = new Set(blogIds);
    if (blogIds) {
      return await this.page(
        Object.assign(
          { isAudit: 1, blogIds: [...set], type: ['faq', 'grass', 'creation'] },
          page
        ),
        {}
      );
    }

    return {
      list: blogList,
      pagination: {
        page: page.page,
        size: page.size,
        total: blogIds.length,
      },
    };
  }

  /**
   * 已赞
   */
  async inLove(userId, page: any) {
    const blogList = null;
    const many = await this.weiboBlogLoveEntity
      .createQueryBuilder('a')
      .where({ userId })
      .orderBy('a.id', 'DESC')
      .getMany();

    const blogIds = many.map(v => {
      return v.blogId;
    });

    const set = new Set(blogIds);

    if (blogIds && blogIds.length) {
      return await this.page(
        Object.assign({ isAudit: 1, blogIds: [...set] }, page),
        {}
      );
    }

    return {
      list: blogList,
      pagination: {
        page: page.page,
        size: page.size,
        total: blogIds.length,
      },
    };
  }

  /**
   * 收藏
   */
  async inCollect(userId, page: any) {
    const blogList = null;
    const many = await this.weiboBlogCollectEntity
      .createQueryBuilder('a')
      .where({ userId })
      .orderBy('a.id', 'DESC')
      .getMany();

    const blogIds = many.map(v => {
      return v.blogId;
    });

    const set = new Set(blogIds);

    if (blogIds && blogIds.length) {
      return await this.page(
        Object.assign({ isAudit: 1, blogIds: [...set] }, page),
        {}
      );
    }

    return {
      list: blogList,
      pagination: {
        page: page.page,
        size: page.size,
        total: blogIds.length,
      },
    };
  }

  /**
   * 已经关注
   * @param userId
   * @param page
   * @returns
   */
  async inFollow(userId, page: any) {
    const blogList = null;
    const many = await this.userFollowEntity
      .createQueryBuilder('a')
      .select('b.*')
      .leftJoin(WeiboBlogEntity, 'b', 'a.user_id = b.user_id')
      .where('a.follow_id = :userId', { userId }) //关注过的用户
      .orderBy('b.id', 'DESC')
      .getRawMany();

    const blogIds = many.map(v => {
      return v.id;
    });

    const set = new Set(blogIds);
    if (blogIds && blogIds.length > 0) {
      return await this.page(
        Object.assign({ isAudit: 1, blogIds: [...set] }, page),
        {}
      );
    }

    return {
      list: blogList,
      pagination: {
        page: page.page,
        size: page.size,
        total: blogIds.length,
      },
    };
  }

  async transformInCollect(arr: [any], userId) {
    if (arr && arr.length) {
      const ids = arr.map(v => v.id);

      const list = await this.weiboBlogCollectEntity
        .createQueryBuilder('a')
        .select('a.*')
        .where('a.blog_id in (:ids)', { ids })
        .andWhere('a.user_id = :userId', { userId })
        .getRawMany();

      const collectIds = list.map(v => v.blog_id);

      arr.map(v => {
        v.is_collect = collectIds.includes(v.id);
      });
    }
    return arr;
  }

  async transformInLove(arr: [any], userId) {
    if (arr && arr.length) {
      const ids = arr.map(v => v.id);

      const list = await this.weiboBlogLoveEntity
        .createQueryBuilder('a')
        .select('a.*')
        .where('a.blog_id in (:ids)', { ids })
        .andWhere('a.user_id = :userId', { userId })
        .getRawMany();

      const loveIds = list.map(v => v.blog_id);

      arr.map(v => {
        v.is_love = loveIds.includes(v.id);
      });
    }
    return arr;
  }

  /**
   * 查询当前活动的blog数量
   * @param activityId
   * @returns 数量
   */
  async findBlogtoActivityCount(activityId: any) {
    return await this.weiboBlogEntity.count({ activity: activityId });
  }

  /**
   * 批量删除博客
   * @param ids 博客id
   */
  async delete(ids: [any]) {
    try {
      await this.weiboBlogPhotoEntity.delete({
        blogId: In(ids),
      });
      await this.weiboBlogEntity.delete({
        id: In(ids),
      });
    } catch (error) {
      throw new CoolCommException(error);
    }
  }
}
